#ifndef HEURISTIC_H 
#define HEURISTIC_H 

#include <vector>
#include <iostream>
#include "network.h"

using namespace std;


class heuristic
{
 public:
 heuristic(network *net, const int nr_nodes = 5,const int nr_arcs = 7):NR_NODES(nr_nodes), NR_ARCS(nr_arcs){
    _net = net;
    capacity_set = false;
    is_undirected = false;
  }
  
  /* -----Put heuristic here--------*/
  
  // Simulating anneling
  //H1 for obj func of building network
  //H2 for obj func of minimize max usage
  //H3 for obj func that is piecewise linear
  //H1split for same obj func as H1 but now is splitting permitted
  double H1(int inp_iter = 200, double inp_T = 4000, double inp_r = 0.73, int nr_changes = 2);
  double H2(int inp_iter = 200, double inp_T = 4000, double inp_r = 0.73, int nr_changes = 2);
  double H3(int inp_iter = 200, double inp_T = 4000, double inp_r = 0.73, int nr_changes = 2);
  double H1split(int inp_iter = 200, double inp_T = 4000, double inp_r = 0.73, int nr_changes = 2);
  double H2split(int inp_iter = 200, double inp_T = 4000, double inp_r = 0.73, int nr_changes = 2);
  double H3split(int inp_iter = 200, double inp_T = 4000, double inp_r = 0.73, int nr_changes = 2);

  //when adding capacities a network with weights == 1 is calculated and then
  //capacities is based on the flow
  void add_capacities(double const const_mult = 2, double const times_mean = 2, int const arc_types = 0);

  vector<int> get_y_values();

  vector<int> heur_node(vector<vector<int> > const &w);

  double get_last_obj_value();

  void set_undirected();

private:
  const int NR_NODES;
  const int NR_ARCS;
  int unique_path;
  int broken_cap;
  double last_obj_value;
  bool capacity_set;
  bool is_undirected;
  enum problemtype {BUILD = 0, Z_SLACK=1, P_LINEAR=2};
  network *_net;
  vector< vector <double> > temp_demand;
  vector< double > flow_tot;
  vector< double > broken_cap_arcs;
  vector< double > capacity;
  vector< int > y_values;
  vector< int > wb;

  // -------Help functions----------

  // Calculates all shortest distance between pair of nodes, path is an NxN-matrix
  void shortest_paths(vector< vector<int> > &path);
  
  // Creats a SP-Graph (the y-variables) given weights
  vector< vector< vector<int> > > shortest_paths_graphs(vector< vector<int> > const &weights);

  double Calc_Cost(vector< vector<int> > const &weights, problemtype );

  // Desides if a node is a leaf in the SP-Ggraph 
  bool is_leaf( vector< vector< vector<int> > > &sp, int leaf, int dest);

  // Calculate the flow in a SP-Graph given one destination
  void update_flow( vector< vector< vector<int> > > &sp, int to_who, int dest, vector< vector <double> > &x, vector< double> &x_tot);

  void init_y_values();

  //-----------Objective functions---------------------------------------//
  double calc_obj_func_z(vector<double> &x_tot);
  double calc_obj_func_build(vector<double> &x_tot);
  double calc_obj_func_p_linear(vector<double> &x_tot);
};

#endif
